package http

import (
	"github.com/gin-gonic/gin"
	"micro-oauth/datamodels/autherror"
	"micro-oauth/datamodels/params"
	"micro-oauth/service"
	"strings"
)

var IntrospectTokenPost = APIWrapper(_introspectTokenPost)
var IssuePosTokenPost = APIWrapper(_issuePosToken)
var RefreshTokenPost = APIWrapper(_refreshTokenPost)

func _refreshTokenPost(c *gin.Context) (interface{}, autherror.HexError) {
	type Req struct {
		RefreshToken string `json:"refresh_token"`
	}
	req := &Req{}
	_ = c.ShouldBindJSON(req)
	if req.RefreshToken == "" {
		return nil, autherror.InvalidData("no refresh token")
	}
	value := c.GetHeader("Authorization")
	accessToken := strings.TrimPrefix(value, "Bearer ")
	if accessToken == "" {
		return nil, autherror.InvalidData("no access token")
	}

	token,hexErr := service.OauthService.RefreshToken(c, accessToken, req.RefreshToken)
	result := map[string]interface{}{}
	if token != nil{
		result = map[string]interface{}{`expires_in`: uint64(token.ExpiresIn.Unix())}
	}
	if hexErr != nil {
		return result, hexErr
	}
	return result, nil
}

func _introspectTokenPost(c *gin.Context) (interface{}, autherror.HexError) {
	token := c.PostForm("access_token")
	apiCode := c.PostForm("api_code")
	if token == "" {
		return nil, autherror.InvalidData("no token")
	}
	req := &params.AuthenticateRequest{
		Token:   token,
		APICode: apiCode,
	}
	if apiCode != "" {
		req.APICode = apiCode
		req.CheckPermission = true
	}
	resp, err := service.OauthService.Authenticate(c, req)
	if err != nil {
		return nil, err
	}
	return resp, nil
}

func _issuePosToken(c *gin.Context) (interface{}, autherror.HexError) {
	type Req struct {
		ClientId     string `form:"client_id" json:"client_id"`
		ClientSecret string `form:"client_secret" json:"client_secret"`
	}
	type Resp struct {
		AccessToken string `json:"access_token"`
		RefreshToken string `json:"refresh_token"`
		TokenType   string `json:"token_type"`
		ExpiresIn   uint64 `json:"expires_in"`
		Scope       string `json:"scope"`
	}
	req := &Req{}
	_ = c.ShouldBindJSON(req)
	if req.ClientId == "" || req.ClientSecret == "" {
		return nil, autherror.InvalidData("params wrong")
	}
	token, hexErr := service.OauthService.IssuePosToken(c, req.ClientId, req.ClientSecret)
	if hexErr != nil {
		return nil, hexErr
	}
	resp := &Resp{
		AccessToken: token.AccessToken,
		RefreshToken: token.RefreshToken,
		TokenType:   string(token.TokenType),
		ExpiresIn:   uint64(token.ExpiresIn.Unix()),
		Scope:       token.ScopeCode,
	}
	return resp, nil
}
